﻿(function ($) {
    // register namespace
    $.extend(true, window, {
        Slick: {
            ExtendedGrid: ExtendedSlickGrid,
            UpdateResponse: { None: 0, Fill: 1, Modify: 2, Add: 3 }

        }
    });
    function ExtendedSlickGrid(controlId, columns, options) {

        function init(grid) {
            var gridOptions = grid.getOptions();
            if (!options.showHeaderRow) {
                gridOptions.hasHeaderFilters = false;
                gridOptions.headerHeight = 36;
            }
            if (options.saveOptions === undefined)
                options.saveOptions = {};
            var control = $(controlId);
//            control.empty();
            var defaultNewItem = options.defaultNewItem === undefined ? { id: -1} : options.defaultNewItem;
            var dataView;
            if (options.enableGrouping) {
                var groupItemMetadataProvider = new Slick.Data.GroupItemMetadataProvider();
                dataView = new Slick.Data.DataView({
                    groupItemMetadataProvider: groupItemMetadataProvider
                });
            } else
                dataView = new Slick.Data.DataView();
            var selectedRowIds = [];
            //            var grid = new Slick.Grid(controlId, dataView, columns, options);
            grid.setData(dataView);
            grid.$control = control;
            var base = {};
            //base.oldRender = grid.render;
            //grid.render = null;
            var data = dataView.getItems();
            grid.setSelectionModel(new Slick.RowSelectionModel());

            // register the group item metadata provider to add expand/collapse group handlers
            if (options.enableGrouping)
                grid.registerPlugin(groupItemMetadataProvider);

            // Highlights the given cell
            var myCustomGrid = {
                // Properties
                columnFilters: options.columnFilters === undefined ? {} : options.columnFilters,
                control: control,
                dataView: dataView,
                data: data,
                sort: {
                    column: options.sortColumn === undefined ? "" : options.sortColumn,
                    direction: options.sortDirection === undefined ? "" : options.sortDirection
                },
                // Methods
                addNewRow: addNewRow,
                base: { render: grid.render },
                block: block,
                clearGrouping: clearGrouping,
                collapseAllGroups: collapseAllGroups,
                expandAllGroups: expandAllGroups,
                filter: filter,
                getGroupedBy: getGroupedBy,
                highlightCell: highlightCell,
                loadData: loadData,
                options: options,
                saveItem: options.saveOptions.method === undefined ? saveItem : options.saveItem,
                saveItemFromDialog: saveItemFromDialog,
                setGroupBy: setGroupBy,
                sortData: sort,
                standardSortComparer: standardSortComparer,
                unblock: unblock,
                updateHeaderRow: updateHeaderRow
            };
            // Extend the grid
            $.extend(grid, myCustomGrid);
            $.extend(grid, this);
            grid.unblock();
            dataView.setFilter(grid.filter);
            // Add events
     

//            grid.onRender.subscribe(function (e, args) {
//                $(controlId).find(' .slick-cell-button').button();
//            });

            grid.onSort.subscribe(function (e, args) {
                sort(args.sortCol.field, args.sortAsc);

            });

            if (options.hasHeaderFilters) {
                $(grid.getHeaderRow()).delegate(":input[type='text']", "change keyup", function (e) {
                    var columnId = $(this).data("columnId");
                    var parent = $(this.parentNode);
                    if (columnId !== undefined && columnId != "undefined")
                        grid.columnFilters[columnId] = $.trim($(this).val());
                    dataView.refresh();
                    parent.children('input').focus();
                });

                $(grid.getHeaderRow()).delegate("select", "change keyup", function (e) {
                    var columnId = $(this).data("columnId");
                    var parent = $(this.parentNode);
                    if (columnId !== undefined && columnId != "undefined")
                        grid.columnFilters[columnId] = $.trim($(this).val());
                    dataView.refresh();

                    parent.children('select').focus();

                });

                grid.onColumnsReordered.subscribe(function (e, args) {
                    updateHeaderRow();
                });

                grid.onColumnsResized.subscribe(function (e, args) {
                    updateHeaderRow();
                });


            }
            grid.onViewportChanged.subscribe(function (e, args) {
                var a = '';
            });

            grid.onSelectedRowsChanged.subscribe(function (e) {
                selectedRowIds = [];
                var rows = grid.getSelectedRows();
                for (var i = 0, l = rows.length; i < l; i++) {
                    var item = dataView.getItem(rows[i]);
                    if (item) selectedRowIds.push(item.id);
                }
            });
            // wire up model events to drive the grid
            dataView.onRowCountChanged.subscribe(function (e, args) {
                grid.updateRowCount();
                grid.invalidate();
                // grid.resizeCanvas();
                grid.render();
                grid.updateHeaderRow();

            });

            dataView.onRowsChanged.subscribe(function (e, args) {
                grid.invalidateRows(args.rows);
                grid.render();
                grid.updateHeaderRow();
                if (selectedRowIds.length > 0) {
                    // since how the original data maps onto rows has changed,
                    // the selected rows in the grid need to be updated
                    var selRows = [];
                    for (var i = 0; i < selectedRowIds.length; i++) {
                        var idx = dataView.getRowById(selectedRowIds[i]);
                        if (idx != undefined)
                            selRows.push(idx);
                    }

                    grid.setSelectedRows(selRows);
                }
            });

            function addNewRow(suspend) {
                grid.dataView.addItem($.extend({}, defaultNewItem));
                if ((suspend === undefined || !suspend) && dataView.isSuspended())
                    grid.dataView.endUpdate();
            }

            function block() {
                control.block({ message: $('#savingBlock'), css: { 'font-size': '20px', width: '200px', height: '30px', 'line-height': '30px', border: '3px solid #000'} });
            }


            function clearGrouping() {
                grid.dataView.groupBy(null);
                groupBy = null;
            }

            function collapseAllGroups() {
                grid.dataView.beginUpdate();
                for (var i = 0; i < grid.dataView.getGroups().length; i++) {
                    grid.dataView.collapseGroup(grid.dataView.getGroups()[i].value);
                }
                grid.dataView.endUpdate();
            }

            function expandAllGroups() {
                grid.dataView.beginUpdate();
                for (var i = 0; i < grid.dataView.getGroups().length; i++) {
                    grid.dataView.expandGroup(grid.dataView.getGroups()[i].value);
                }
                grid.dataView.endUpdate();
            }

            function filter(item) {
                var columnFilters = grid.columnFilters;

                for (var columnId in columnFilters) {
                    if (columnId !== undefined && columnFilters[columnId] !== "") {
                        var c = grid.getColumns()[grid.getColumnIndex(columnId)];
                        if (c !== undefined)
                            if (item.id != -1 && (item[c.field] + "").indexOf(columnFilters[columnId]) == -1)
                                return false;
                    }
                }
                return true;
            }

            function highlightCell(row, cell) {
                var $cell = $(grid.getCellNode(row, cell));
                $cell.stop(true, true).effect("highlight", { color: "red" }, 1000);
            }

            var groupBy = "";

            function getGroupedBy() {
                return groupBy;
            }

            function loadData(dataToLoad) {
                dataView.setItems(dataToLoad);
                if (dataView.getLength() == 0)
                    updateHeaderRow();
                sort(options.sortColumn, options.sortDirection);
                //sort();
            }

            function saveItem(item) {
                grid.block();
                var args = {};
                if (options.saveOptions.buildItem !== undefined)
                    options.saveOptions.buildItem(item, args);

                if (options.saveOptions.itemName !== undefined)
                    args[options.saveOptions.itemName] = item;
                else
                    args.item = item;
                setTimeout(function () {
                    var errorMsg = options.saveOptions.errorMessage === undefined ? 'An error has occurred. Please refresh the page and try again.' : options.saveOptions.errorMessage;
                    $.ajax({
                        url: options.saveOptions.url,
                        data: JSON.stringify(args),
                        error: function () {
                            alert(errorMsg);
                            control.unblock();
                        },
                        success: function (response) {
                            if (response.d)
                                response = response.d;
                            var newData = response.Data;

                            if (response.Result) {
                                if (options.saveOptions.updateResponse == Slick.UpdateResponse.Fill)
                                    loadData();
                                else if (options.saveOptions.updateResponse == Slick.UpdateResponse.Modify) {
                                    item.id = newData.id;
                                    sort();
                                    //grid.dataView.sort();
                                    if (dataView.isSuspended())
                                        dataView.endUpdate();
                                }
                            } else {
                                alert(response.Data, "Server Error", undefined, 500, 400);
                            }
                            grid.unblock();
                        }
                    });
                }, 500);
            }

            function saveItemFromDialog($element, itemName, url, buildItem, errorMessage, updateResponse, success) {
                $element.block({ message: $('#savingBlock'), css: { 'font-size': '20px', width: '200px', height: '30px', 'line-height': '30px', border: '3px solid #000'} });
                var args = {};
                var item = buildItem();
                args[itemName] = item;

                setTimeout(function () {
                    var errorMsg = errorMessage === undefined ? 'An error has occurred. Please refresh the page and try again.' : errorMessage;
                    $.ajax({
                        url: url,
                        data: JSON.stringify(args),
                        error: function () {
                            alert(errorMsg);
                            control.unblock();
                        },
                        success: function (response) {
                            if (response.d)
                                response = response.d;
                            var newData = response.Data;

                            if (response.Result) {
                                if (updateResponse == Slick.UpdateResponse.Fill)
                                    loadData();
                                else if (updateResponse == Slick.UpdateResponse.Add) {
                                    grid.dataView.addItem(newData);
                                    grid.dataView.sort();
                                    success();
                                }
                            } else {
                                alert(response.Data);
                            }
                            $element.unblock();
                        }
                    });
                }, 500);
            }

            function setGroupBy(grouping) {
                groupBy = grouping;
            }

            function sort(column, sortAscending) {
                if (column === undefined)
                    column = grid.sort.column;
                else
                    grid.sort.column = column;

                if (sortAscending === undefined)
                    sortAscending = grid.sort.direction == 1;
                else
                    grid.sort.direction = sortAscending ? 1 : -1;

                if ($.browser.msie && $.browser.version <= 8) {
                    // using temporary Object.prototype.toString override
                    // more limited and does lexicographic sort only by default, but can be much faster

                    // use numeric sort of % and lexicographic for everything else
                    dataView.fastSort(column, sortAscending);
                } else {
                    // using native sort with comparer
                    // preferred method but can be very slow in IE with huge datasets
                    dataView.sort(standardSortComparer, sortAscending);
                }
            }

            function standardSortComparer(a, b) {
                var x = a[grid.sort.column], y = b[grid.sort.column];
                return (x == y ? 0 : (x > y ? 1 : -1));
            }

            function unblock() {
                control.unblock();
            }

            function updateHeaderRow() {
                if (!options.hasHeaderFilters)
                    return;
                //            if (dataView.getItems().length == 0)
                //                $('.slick-headerrow-columns').hide();
                //            else {

                var showFilter = false;
                for (var i = 0; i < columns.length; i++) {
                    var colWidth = columns[i].width;
                    var header = grid.getHeaderRowColumn(columns[i].id);
                    $(header).empty();
                    if (!("showFilter" in columns[i]) || !columns[i].showFilter) {
                        $("<div></div>").width(colWidth - 10).height(options.headerRowHeight).css({ opacity: 0 }).appendTo(header);
                        $(header).css("padding-bottom", "0px");
                        $(header).css("padding-top", "0px");
                        continue;
                    }
                    showFilter = true;
                    $(header).show();
                    //$(header).width(colWidth);

                    //                if (columns[i].id == "status")
                    //                    $("<SELECT tabIndex='0' class='editor-projectStatus'><Option value=''></option><OPTION value='1'>Active</OPTION><OPTION value='3'>Cancelled</OPTION><OPTION value='0'>Complete</OPTION><OPTION value='[^0]'>Incomplete</OPTION><OPTION value='2'>Open</OPTION></SELECT>")
                    //                            .data("columnId", columns[i].id)
                    //                            .width(colWidth - 3)
                    //                            .val(grid.columnFilters[columns[i].id])
                    //                            .appendTo(header);
                    //                else
                    $("<input type='text'>")
                        .data("columnId", columns[i].id)
                        .width(colWidth - 14)
                        .val(grid.columnFilters[columns[i].id])
                        .appendTo(header);
                    //                }
                }
                if (showFilter)
                    $(grid.control.selector + ' .slick-headerrow-columns').show();
                else
                    $(grid.control.selector + ' .slick-headerrow-columns').hide();
            }


            // return grid;
        }

        function destroy() {
        }

        return {
            "init": init,
            "destroy": destroy
        };
    }
})(jQuery);
 